﻿using Newtonsoft.Json;
using PMIS.Common.Dialog;
using PMIS.HttpRequest;
using PMIS.Shared.DTO;
using PMIS.Shared.Models;

namespace PMIS.ViewModels.Menu
{
    public class MenuAuthorizeViewModel : DialogViewModelBase
    {
        private string _roleId;

        private bool _cascadeSelect = false;

        private readonly HttpService _httpService;

        public MenuAuthorizeViewModel(HttpService httpService)
        {
            _httpService = httpService;

            LoadNavMenu();
        }

        private List<MenuDto>? _allMenuList;
        public List<MenuDto>? AllMenuList
        {
            get { return _allMenuList; }
            set { SetProperty(ref _allMenuList, value); }
        }

        private List<MenuDto>? _treeMenuList;
        public List<MenuDto>? TreeMenuList
        {
            get { return _treeMenuList; }
            set { SetProperty(ref _treeMenuList, value); }
        }

        private List<DataDictDto> _dataDictList;

        private async void LoadNavMenu()
        {
            var response = await _httpService.GetAsync(Api.MENU_GET_LIST);
            if (response?.code == 1)
            {
                var data = JsonConvert.DeserializeObject<PagingModel<MenuDto>>(JsonConvert.SerializeObject(response.data));
                AllMenuList = data.Items.OrderBy(p => p.Sort).ToList();

                var menuIdList = await LoadMenuAuthorizeList();

                await LoadDataDict();

                foreach (var item in AllMenuList)
                {
                    foreach (var dataDict in _dataDictList)
                    {
                        if (item.Type == dataDict.DictKey)
                        {
                            item.TypeName = dataDict.DictName;
                        }
                    }
                    foreach (var menuId in menuIdList)
                    {
                        if (item.Id == menuId)
                        {
                            item.IsChecked = true;
                        }
                    }
                }

                LoadTreeMenuList();
            }
        }

        private async Task<List<string>>? LoadMenuAuthorizeList()
        {
            var parameters = new Dictionary<string, object>();
            parameters["roleId"] = _roleId;
            var response = await _httpService.GetAsync(Api.ROLE_GET_ROLEAUTHORIZELIST, parameters);
            if (response?.code == 1)
            {
                var data = JsonConvert.DeserializeObject<List<string>>(JsonConvert.SerializeObject(response.data));
                return data;
            }
            return [];
        }

        private async Task LoadDataDict()
        {
            var parameters = new Dictionary<string, object>();
            parameters["dictType"] = "MenuType";
            var response = await _httpService.GetAsync(Api.DATADICT_GET_LIST, parameters);
            if (response?.code == 1)
            {
                var data = JsonConvert.DeserializeObject<PagingModel<DataDictDto>>(JsonConvert.SerializeObject(response.data));
                _dataDictList = data.Items;
            }
        }

        private void LoadTreeMenuList()
        {
            var allMenus = AllMenuList;
            TreeMenuList = new List<MenuDto>(allMenus.Where(x => x.ParentId == null));
            foreach (var item in TreeMenuList)
            {
                item.IsExpanded = true;
                LoadChildMenuList(item);
            }
        }

        public void LoadChildMenuList(MenuDto menu)
        {
            var allMenus = AllMenuList;
            menu.Children = allMenus.Where(x => x.ParentId == menu.Id).ToList();
            foreach (var subitem in menu.Children)
            {
                // Recursive call
                LoadChildMenuList(subitem);
            }
        }
        private DelegateCommand<object> _checkCommand;
        public DelegateCommand<object> CheckCommand => _checkCommand ??= new DelegateCommand<object>(OnCheck);

        private DelegateCommand<object> _toggleCommand;
        public DelegateCommand<object> ToggleCommand => _toggleCommand ??= new DelegateCommand<object>(OnToggle);

        private DelegateCommand<object> _cascadeSelectionCommand;
        public DelegateCommand<object> CascadeSelectionCommand => _cascadeSelectionCommand ??= new DelegateCommand<object>(OnCascadeSelection);

        private DelegateCommand _saveCommand;
        public DelegateCommand SaveCommand => _saveCommand ??= new DelegateCommand(OnSave);

        private DelegateCommand _cancelCommand;
        public DelegateCommand CancelCommand => _cancelCommand ??= new DelegateCommand(OnCancel);


        private async void OnSave()
        {
            var menuList = new List<MenuDto>();
            foreach (var item in this.TreeMenuList)
            {
                menuList.AddRange(item.GetCheckedNodes());
            }
            var menuIdList = menuList.Where(x => x.IsChecked == true).Select(x => x.Id).ToList();

            var data = new MenuAuthorizeDto();
            data.RoleId = _roleId;
            data.MenuList = menuIdList;
            var response = await _httpService.PostAsync(Api.ROLE_SET_ROLEAUTHORIZE, data);
            if (response?.code == 1)
            {
                CloseDialog(new DialogResult(ButtonResult.Yes));
            }
            else
            {

            }
        }

        private void OnCancel()
        {
            CloseDialog(new DialogResult(ButtonResult.Cancel));
        }

        private void OnCheck(object parameter)
        {
            if (parameter is MenuDto menu)
            {
                if (_cascadeSelect)
                {
                    bool isChecked = menu.IsChecked ?? true;
                    menu.SelectAll(isChecked);
                }
            }
        }

        private void OnToggle(object parameter)
        {
            if (parameter is bool value)
            {
                if (value)
                {
                    this.TreeMenuList.ForEach(x => x.SelectAll(true));
                }
                else
                {
                    this.TreeMenuList.ForEach(x => x.SelectAll(false));
                }
            }
        }

        private void OnCascadeSelection(object parameter)
        {
            if (parameter is bool value)
            {
                _cascadeSelect = value;
            }
        }

        public override void OnDialogOpened(IDialogParameters parameters)
        {
            if (parameters.Count > 0)
            {
                _roleId = parameters.GetValue<string>("roleId");
            }
        }
    }
}
